package com.rules.admin.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps;
import com.rules.admin.dao.PermissionReferenceDao;
import com.rules.admin.entity.*;
import com.rules.admin.login.UserHolder;
import com.rules.admin.service.PermissionService;
import com.rules.admin.service.RulePackageService;
import com.rules.admin.service.SysGroupUserRoleService;
import com.rules.admin.vo.RuleUser;
import com.rules.admin.vo.ProjectRoleVO;
import com.rules.admin.vo.PackageRoleVO;


import com.rules.admin.service.ProjectService;
import com.rules.admin.utils.ResultUtils;



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.stream.Collectors;

@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionReferenceDao, PermissionReference> implements PermissionService {

   @Autowired
   private SysGroupUserRoleService sysGroupUserRoleService;
   @Autowired
   private RulePackageService rulePackageService;
   @Autowired
   private UserHolder<RuleUser> userHolder;
   @Autowired
   private ProjectService projectService;

   public Map<Long, ProjectRoleVO> getCurrentUserProjectRole(Long userId) {
      Map<Long, ProjectRoleVO> projectRoleVOMap = Maps.newConcurrentMap();
      List<SysGroupUserRole> sysGroupUserRoles = this.sysGroupUserRoleService.getByUserId(userId);
      List<Long> groupIds = sysGroupUserRoles.stream().map(item->item.getGroupId()).distinct().collect(Collectors.toList());
      this.mergeUserGroupPermission(groupIds, projectRoleVOMap);
      this.mergeUserPermission(projectRoleVOMap, userId);
      return projectRoleVOMap;
   }

   public Map<String, Object> getPermissions(Long packageId) {
      Map<Long, ProjectRoleVO> map = this.projectService.getProjectRoleVOs(((RuleUser)this.userHolder.getUser()).getId());
      RulePackage rulePackage = this.rulePackageService.getById(packageId);
      if (rulePackage != null && map.containsKey(rulePackage.getProjectid())) {
         Map<Long, PackageRoleVO> packageRoleVOMap = ((ProjectRoleVO)map.get(rulePackage.getProjectid())).getPackageRoles();
         if (((PackageRoleVO)packageRoleVOMap.get(packageId)).getRoles().contains(1) || ((PackageRoleVO)packageRoleVOMap.get(packageId)).getRoles().contains(0)) {
            return ResultUtils.getSuccessResultData();
         }
      }

      return ResultUtils.getFaildResultData();
   }

   public Map<String, Object> permissionsJudgment(Long packageId) {
      Map<Long, ProjectRoleVO> map = this.projectService.getProjectRoleVOs(((RuleUser)this.userHolder.getUser()).getId());
      RulePackage rulePackage = (RulePackage)this.rulePackageService.getById(packageId);
      if (rulePackage != null && map.containsKey(rulePackage.getProjectid())) {
         Map<Long, PackageRoleVO> packageRoleVOMap = ((ProjectRoleVO)map.get(rulePackage.getProjectid())).getPackageRoles();
         if (packageRoleVOMap.containsKey(packageId)) {
            return ResultUtils.getSuccessResultData();
         }
      }

      return ResultUtils.getFaildResultData();
   }

   @Override
   public List<PackagePermissions> selectPackageOfPermission(long projectId, List<Long> ownerIds) {
      return this.baseMapper.selectPackageOfPermission(projectId,ownerIds);
   }

   @Override
   public List<PermissionReference> getPermissionReferencesByOwnerId(Long userId) {
      LambdaQueryWrapper<PermissionReference> queryWrapper = new LambdaQueryWrapper<>();
      queryWrapper.eq(PermissionReference::getOwnerId,userId).eq(PermissionReference::getTargetType,1);
      return this.baseMapper.selectList(queryWrapper);
   }

   @Override
   public List<ProjectPermissions> selectProjectOfPermission(List ownerIds) {
      return this.baseMapper.selectProjectOfPermission(ownerIds);
   }

   private void mergeUserPermission(Map<Long, ProjectRoleVO> projectRoleVOMap, Long userId) {
      LambdaQueryWrapper<PermissionReference> queryWrapper = new LambdaQueryWrapper<>();
      queryWrapper.eq(PermissionReference::getOwnerId,userId).eq(PermissionReference::getTargetType,0);
      List<PermissionReference> permissionReferences = this.baseMapper.selectList(queryWrapper);

      this.analyseProjectPermission(permissionReferences, projectRoleVOMap);
      LambdaQueryWrapper<PermissionReference> queryWrapper1 = new LambdaQueryWrapper<>();
      queryWrapper1.eq(PermissionReference::getOwnerId,userId).eq(PermissionReference::getTargetType,0);
      permissionReferences = this.baseMapper.selectList(queryWrapper1);
      this.analysePackagePermission(projectRoleVOMap, permissionReferences);
   }

   private void analyseProjectPermission(List<PermissionReference> permissionReferences, Map<Long, ProjectRoleVO> projectRoleVOMap) {
      List<Long> projectIds = Lists.transform(permissionReferences, new Function<PermissionReference, Long>() {
         public Long apply(PermissionReference input) {
            return input.getTargetId();
         }
      });
      List<RulePackage> rulePackages = this.rulePackageService.getRulePackagesByProjectIds(projectIds);
      ImmutableListMultimap<Long, RulePackage> rulePackageGroupByProjectId = Multimaps.index(rulePackages, new Function<RulePackage, Long>() {
         public Long apply(RulePackage input) {
            return input.getProjectid();
         }
      });
      this.analyseProjectPermissions(permissionReferences, rulePackageGroupByProjectId, projectRoleVOMap);
   }

   private void mergeUserGroupPermission(List<Long> groupIds, Map<Long, ProjectRoleVO> projectRoleVOMap) {
      List<PermissionReference> permissionReferences = this.getPermissionReferenceByGroupIds(groupIds,0L);
      List<RulePackage> packages = this.getPackageInProjectPermission(permissionReferences);
      ImmutableListMultimap<Long, RulePackage> groupPackages = Multimaps.index(packages, new Function<RulePackage, Long>() {
         public Long apply(RulePackage input) {
            return input.getProjectid();
         }
      });
      this.analyseProjectPermissions(permissionReferences, groupPackages, projectRoleVOMap);
      this.analysePackagePermission(groupIds, projectRoleVOMap);
   }

   private void analysePackagePermission(Map<Long, ProjectRoleVO> projectRoleVOMap, List<PermissionReference> permissionReferences) {
      ImmutableListMultimap<Long, PermissionReference> permissionReferenceGroup = Multimaps.index(permissionReferences, new Function<PermissionReference, Long>() {
         public Long apply(PermissionReference input) {
            return input.getTargetId();
         }
      });
      List<Long> packageIds = Lists.transform(permissionReferences, new Function<PermissionReference, Long>() {
         public Long apply(PermissionReference input) {
            return input.getTargetId();
         }
      });


      List<RulePackage> rulePackages = this.rulePackageService.getRulePackagesBypackageIds(packageIds);
      Iterator var7 = rulePackages.iterator();

      while(var7.hasNext()) {
         RulePackage rulePackage = (RulePackage)var7.next();
         ProjectRoleVO projectRoleVO = (ProjectRoleVO)projectRoleVOMap.get(rulePackage.getProjectid());
         if (projectRoleVO == null) {
            projectRoleVO = new ProjectRoleVO();
            projectRoleVOMap.put(rulePackage.getProjectid(), projectRoleVO);
            projectRoleVO.setId(rulePackage.getProjectid());
            HashSet<Integer> hashSet = new HashSet();
            hashSet.add(2);
            projectRoleVO.setRoles(hashSet);
         }

         PackageRoleVO packageRoleVO = (PackageRoleVO)projectRoleVO.getPackageRoles().get(rulePackage.getId());
         if (packageRoleVO == null) {
            packageRoleVO = new PackageRoleVO();
            packageRoleVO.setId(rulePackage.getId());
            projectRoleVO.getPackageRoles().put(rulePackage.getId(), packageRoleVO);
         }

         List<PermissionReference> permissions = permissionReferenceGroup.get(rulePackage.getId());
         Iterator var12 = permissions.iterator();

         while(var12.hasNext()) {
            PermissionReference permissionReference = (PermissionReference)var12.next();
            packageRoleVO.getRoles().add(permissionReference.getMode());
         }
      }

   }
   private List<PermissionReference> getPermissionReferenceByGroupIds(List<Long> groupIds,Long targetType) {
      LambdaQueryWrapper<PermissionReference> queryWrapper = new LambdaQueryWrapper();
      if (groupIds.size() > 0) {
         queryWrapper.in(PermissionReference::getOwnerId, groupIds).eq(PermissionReference::getTargetType, targetType);
      } else {
         queryWrapper.eq(PermissionReference::getId, -1L);
      }

      return this.baseMapper.selectList(queryWrapper);
   }


   private void analysePackagePermission(List<Long> groupIds, Map<Long, ProjectRoleVO> projectRoleVOMap) {

      List<PermissionReference> permissionReferences = getPermissionReferenceByGroupIds(groupIds,1l);
      this.analysePackagePermission(projectRoleVOMap, permissionReferences);
   }

   private Map<Long, ProjectRoleVO> analyseProjectPermissions(List<PermissionReference> permissionReferences, ImmutableListMultimap<Long, RulePackage> groupPackages, Map<Long, ProjectRoleVO> projectRoleVOMap) {
      Iterator var4 = permissionReferences.iterator();

      while(var4.hasNext()) {
         PermissionReference permissionReference = (PermissionReference)var4.next();
         ProjectRoleVO projectRoleVO;
         if (projectRoleVOMap.containsKey(permissionReference.getTargetId())) {
            projectRoleVO = (ProjectRoleVO)projectRoleVOMap.get(permissionReference.getTargetId());
         } else {
            projectRoleVO = new ProjectRoleVO();
            projectRoleVOMap.put(permissionReference.getTargetId(), projectRoleVO);
            projectRoleVO.setId(permissionReference.getTargetId());
         }

         projectRoleVO.getRoles().add(permissionReference.getMode());
         Map<Long, PackageRoleVO> packageRuleVoMaps = projectRoleVO.getPackageRoles();
         List<RulePackage> rulePackages = groupPackages.get(permissionReference.getTargetId());
         if (rulePackages != null) {
            this.setPackagePermissionRoles(permissionReference, packageRuleVoMaps, rulePackages);
         }
      }

      return projectRoleVOMap;
   }

   private List<RulePackage> getPackageInProjectPermission(List<PermissionReference> permissionReferences) {
      List<Long> projectIds = Lists.transform(permissionReferences, new Function<PermissionReference, Long>() {
         public Long apply(PermissionReference input) {
            return input.getTargetId();
         }
      });
      return this.rulePackageService.getRulePackagesByProjectIds(projectIds);
   }

   private void setPackagePermissionRoles(PermissionReference permissionReference, Map<Long, PackageRoleVO> packageRuleVoMaps, List<RulePackage> rulePackages) {
      PackageRoleVO packageRoleVO;
      for(Iterator iterator = rulePackages.iterator(); iterator.hasNext(); packageRoleVO.getRoles().add(permissionReference.getMode())) {
         RulePackage rulePackage = (RulePackage)iterator.next();
         if (packageRuleVoMaps.containsKey(rulePackage.getId())) {
            packageRoleVO = (PackageRoleVO)packageRuleVoMaps.get(rulePackage.getId());
         } else {
            packageRoleVO = new PackageRoleVO();
            packageRoleVO.setId(rulePackage.getId());
            packageRuleVoMaps.put(rulePackage.getId(), packageRoleVO);
         }
      }

   }
}
